﻿using HP.HPTRIM.SDK;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DocumentAccess
{
    public class TrimDocumentStream : Stream, IDisposable
    {

        private DocumentStream _docStream = null;
        private Record _record;


        public TrimDocumentStream(Record record)
        {
            _record = record;

            _docStream = new DocumentStream(_record, false, null, null);

            // We call GetAvailableData() in the constructor to initiate start the download of the document.
            // Until we do this we have no knowledge of the electronic document, the main problem with this is that 
            // we do not know its size and are unable to return a value for the Length property.
            //
            // We do not use _record.DocumentSize for the Length property as there have been instances where a customer has
            // imported data and had inaccurate values in DocumentSize
            uint bytesRead = 0;
            while (!_docStream.Done() && bytesRead == 0)
            {
                bytesRead = _docStream.GetAvailableData(new byte[1]);
            }
            
            _docStream.Seek(0);

        }


        public override bool CanRead
        {
            get { return true; }
        }

        public override bool CanSeek
        {
            get { return true; }
        }

        public override bool CanWrite
        {
            get { return false; }
        }

        public override void Flush()
        {
            throw new NotImplementedException();
        }

        public override long Length
        {
            get
            {
                return _docStream.Length;
            }
        }

        private long _bytesSoFar = 0;
        public override long Position
        {
            get { return _bytesSoFar; }
            set { _bytesSoFar = value; }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            uint bytesRead = 0;

            while (!_docStream.Done() && bytesRead == 0 && bytesRead < count)
            {
                bytesRead = _docStream.GetAvailableData(buffer);

                if (bytesRead == 0)
                {
                    Thread.Sleep(100);
                }

                _bytesSoFar += bytesRead;

            }
            return Convert.ToInt32(bytesRead);
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            if (origin == SeekOrigin.Begin)
            {
                _bytesSoFar = 0;
            }

            if (origin == SeekOrigin.End)
            {
                _bytesSoFar = _docStream.Length;
            }

            _bytesSoFar = _bytesSoFar + offset;

            _docStream.Seek(_bytesSoFar);

            return _bytesSoFar;
        }

        public override void SetLength(long value)
        {
            throw new NotImplementedException();
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            throw new NotImplementedException();
        }



        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_docStream != null)
                {
                    _docStream.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        public void WriteTo(Stream responseStream)
        {
            var data = new byte[4096];
            int bytesRead;

            while ((bytesRead = this.Read(data, 0, data.Length)) > 0)
            {
                responseStream.Write(data, 0, bytesRead);
                responseStream.Flush();
            }
        }

    }
}
